package dblockcache;

import java.io.IOException;

import virtualdisk.Disk;
import common.Constants;
import java.lang.IllegalArgumentException;

public class Buffer extends DBuffer {

	public Disk _disk;
	public int _blockID;

	private boolean _isClean;
	private boolean _isValid;
	private byte[] _buffer;
	
	private volatile boolean inUse;

	public Buffer() {
		// _blockID = blockID;
		inUse = false;
	}

	@Override
	public void startFetch() {
		try {
			_disk.startRequest(this, Constants.DiskOperationType.READ);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void startPush() {
		try {
			_isValid = false;
			_disk.startRequest(this, Constants.DiskOperationType.WRITE);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean checkValid() {
		return _isValid;
	}

	@Override
	public boolean waitValid() {
		// is valid after a read from DFS finishes
		while (!checkValid()) {
			// spin?
		}
		return true;
	}

	@Override
	public boolean checkClean() {
		return _isClean;
	}

	@Override
	public boolean waitClean() {
		while (!checkClean()) {
			// spin?
		}
		return true;
	}

	@Override
	public boolean isBusy() {
		// if lock is held, return false
		// else, return true
		return false;
	}

	/*
	 * reads into the buffer[] array from the contents of the DBuffer. Check
	 * first that the DBuffer has a valid copy of the data! startOffset and
	 * count are for the buffer array, not the DBuffer. Upon an error, it should
	 * return -1, otherwise return number of bytes read.
	 */
	@Override
	public int read(byte[] buffer, int startOffset, int count) {
		if (!_isValid) {
			waitValid();
		}
		// read
		try {
			int j = 0;
			for (int i = startOffset; i < count; i++) {
				buffer[i] = _buffer[j];
				j++;
			}
			return count;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

	/*
	 * writes into the DBuffer from the contents of buffer[] array. startOffset
	 * and count are for the buffer array, not the DBuffer. Mark buffer dirty!
	 * Upon an error, it should return -1, otherwise return number of bytes
	 * written.
	 */
	@Override
	public int write(byte[] buffer, int startOffset, int count) {
		_isClean = false;
		try {
			int j = 0;
			// write
			for (int i = startOffset; i < count; i++) {
				_buffer[j] = buffer[i];
				j++;
			}
			return count;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

	@Override
	public void ioComplete() {
		// called by disk, says it's done reading/writing
		_isValid = true;
	}

	@Override
	public int getBlockID() {
		return _blockID;
	}

	@Override
	public byte[] getBuffer() {
		return _buffer;
	}

	@Override
	public void setBlockID(int blockID) {
		_blockID = blockID;
	}
	
	@Override
	public void setClean (boolean bool) {
		_isClean = bool;
	}
	
	public boolean isInUse() {
		return inUse;
	}

	public void setInUse(boolean bool) {
		inUse = bool;
	}
}
